package com.xinxing.city.recoverycheck.serialport;

import android.os.Handler;
import android.util.Log;

import com.xinxing.city.recoverycheck.Constant;
import com.xinxing.city.recoverycheck.entitys.KernelAction;
import com.xinxing.city.recoverycheck.entitys.KernelActions;
import com.xinxing.city.recoverycheck.interfaces.ICallBackWeight;
import com.xinxing.city.recoverycheck.interfaces.IDeviceKernel;
import com.xinxing.city.recoverycheck.interfaces.ISerialSendReceiveData;
import com.xinxing.city.recoverycheck.util.StringUtil;

import org.greenrobot.eventbus.EventBus;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;

public class SerialSendReceiveData implements ISerialSendReceiveData {
    private static SerialPortHelper serialPortHelper;
    private boolean isOverFlow = true;
    private int overCount = 0;
    private boolean overFlow1 = false;
    private boolean overFlow2 = false;
    private boolean overFlow3 = false;
    private boolean overFlow4 = false;


    private Handler handler = new Handler();

    @Override
    public void start(String sPort, int iBaudRate, IDeviceKernel kernel) {

//        Map<Integer, Long> anyWeight = new HashMap<>();
//        appRuntime = DI.getInstance(APPRuntime.class);
//        Log.e("TTT", "准备初始化串口  ");

        try {
            serialPortHelper = new SerialPortHelper(sPort, iBaudRate) {
                @Override
                protected void onDataReceived(byte[] buffer, int size) {
                    String res = StringUtil.byte2HexStr(buffer);
                    Log.e("Serial", res);
                    List<String> params = new ArrayList<>();
                    switch (buffer[2]) {
                        case (byte) 0x11://门操作
                            int type = (int) buffer[4];
                            Log.e("TTT","type "+type);
                            params.add(res);
                            if(type == 0){
                                Log.e("TTT","交投门关");
                                EventBus.getDefault().post(new KernelAction(KernelActions.R_CLOSE_DOOR, params));
                            }else if(type == 1){
                                Log.e("TTT","交投门开");
                                EventBus.getDefault().post(new KernelAction(KernelActions.R_OPEN_DOOR, params));
                            }else if(type == 2){
                                Log.e("TTT","清运门开");
                                EventBus.getDefault().post(new KernelAction(KernelActions.R_CLEAN_DOOR, params));
                            }
                            break;
                        case (byte) 0x13://称重

                                Log.e("Serial","重量");
                                params.add(res);
                                int roomNumber2 = buffer[3];
                                long weightotal = bytesToInt2(new byte[]{buffer[4], buffer[5], buffer[6], buffer[7]});
                                params.add(weightotal+"");
                                EventBus.getDefault().post(new KernelAction(KernelActions.R_WEIGHT, params));

                            break;
                        case (byte) 0x17://开门锁
                            params.add(res);
                            break;
                        case (byte) 0x15://故障
                            if (Constant.FACTORY == Constant.CHENGKAI) {

                                if ((int) buffer[3] == 2) {
                                    params.add(String.valueOf(1));
                                    EventBus.getDefault().post(new KernelAction(KernelActions.DOOR_START, params));
//                                    closeDoorState((int) buffer[3]);
                                } else if ((int) buffer[3] == 1) {
//                                    List<String> params = new ArrayList<>();
//                                    closeDoorState((int)buffer[3]);
                                    params.add(res);
                                    EventBus.getDefault().post(new KernelAction(KernelActions.R_CLOSE_DOOR, params));
                                } else if ((int) buffer[3] == 3) {//压缩开启
//                                    closeDoorState((int) buffer[3]);

                                    params.add("1");
                                    EventBus.getDefault().post(new KernelAction(KernelActions.R_42_ZIP, params));

                                } else if ((int) buffer[3] == 4) {//压缩结束
//
                                    params.add("0");
                                    EventBus.getDefault().post(new KernelAction(KernelActions.R_42_ZIP, params));
                                } else if((int) buffer[3] == 5){//已满溢

                                    params.add("1");
                                    EventBus.getDefault().post(new KernelAction(KernelActions.R_23_OVER, params));
                                }else if((int) buffer[3] == 6){//未满溢

                                    params.add("0");
                                    EventBus.getDefault().post(new KernelAction(KernelActions.R_23_OVER, params));
                                }else if ((int) buffer[3] == 7) {//清运门开
                                    params.add(res);
                                    EventBus.getDefault().post(new KernelAction(KernelActions.R_0C_CLEAN, params));
                                }else if((int) buffer[3] == 8){//清运门关
                                    params.add(res);
                                    EventBus.getDefault().post(new KernelAction(KernelActions.R_COLSE_CLEAN, params));
                                }
                                closeDoorState((int) buffer[3]);
                            } else {
                                Log.e("TTT", "故障码：" + buffer[3] + "   数据：" + buffer[4]);
//                                Constant.FaultCode = buffer[3];
//                                Constant.FaultData = buffer[4];
                            }
                            break;
                        case (byte) 0x14://满溢
                            if (Constant.FACTORY==Constant.CHENGKAI) {
                                int door = (int) buffer[3];
                                int over = (int) buffer[4];
                                int clean_door = (int) buffer[5];
                                int zip = (int) buffer[6];

                                List<String> params5 = new ArrayList<>();
                                params5.add(String.valueOf(door));
                                params5.add(String.valueOf(over));
                                params5.add(String.valueOf(clean_door));
                                params5.add(String.valueOf(zip));
                                EventBus.getDefault().post(new KernelAction(KernelActions.STATE, params5));
                            }else {
//                            if (buffer[4] == 1) {//满溢状态,数据：00未满01满溢 02压缩（仅一号位）
////                                Constant.OVERRLOW.put((int) buffer[3], (int) buffer[5]);
//////                                overFlowListener.overFlowState(overFlow1,overFlow2,overFlow3,overFlow4);
////                                List<String> params = new ArrayList<>();
////                                params.add(String.valueOf((int) buffer[3]));
////                                if (buffer[5] == 1) {
////                                    EventBus.getDefault().post(new KernelAction(KernelActions.OVERRLOW, params));
////                                }
////                                if (buffer[5] == 2) {
////                                    EventBus.getDefault().post(new KernelAction(KernelActions.ZIP, params));
////                                }
//                            } else if (buffer[4] == 2) {//投口状态, 数据：00关门完成 01开门 02关门中
////                                if( Constant.DOOR_STATE.containsKey((int)buffer[3])){
////
////                                    int type = Constant.DOOR_STATE.get((int)buffer[3]);
////                                    Log.e("serial ","Type:  "+type+"   bu "+(int)buffer[5]);
////                                    if(type != (int)buffer[5]){
////                                        Constant.DOOR_STATE.put((int) buffer[3], (int) buffer[5]);
////                                        List<String> params = new ArrayList<>();
////                                        params.add(String.valueOf((int) buffer[3]));
////                                        EventBus.getDefault().post(new KernelAction(KernelActions.DOOR_START, params));
////                                    }
////                                }else {
////                                Constant.DOOR_STATE.put((int) buffer[3], (int) buffer[5]);
////                                List<String> params = new ArrayList<>();
////                                params.add(String.valueOf((int) buffer[3]));
////                                EventBus.getDefault().post(new KernelAction(KernelActions.DOOR_START, params));
////                                }
//                            } else if (buffer[4] == 3) {//清运门状态,数据：00清运门关闭 01清运门开启
////                                Constant.CLEAN_DOOR_STATE.put((int) buffer[3], (int) buffer[5]);
////                                List<String> params = new ArrayList<>();
////                                params.add(String.valueOf((int) buffer[3]));
////                                EventBus.getDefault().post(new KernelAction(KernelActions.CLEAN_DOOR_START, params));
//                            }
                                int overState = (int) buffer[4];

                                int cleanState = (int) buffer[5];
                                params.add(res);
                                params.add("" + overState);
                                params.add("" + cleanState);

                                EventBus.getDefault().post(new KernelAction(KernelActions.R_WEIGHT, params));
                            }
                            break;
                        case (byte) 0x80://关门上报
                            int roomNum = buffer[4];
                            int errorCode = buffer[3];
                            int errorCount = buffer[5];
                            if (errorCount > 5) {
                                Log.e("Serial", roomNum + "号关门次数超过5次失败,错误码：" + errorCode);
                            }
                            break;
                        case (byte) 0x16:
                            int zipState = (int)buffer[3];
                            break;
                    }

                }
            };
            serialPortHelper.open();
        } catch (IOException e) {
            Log.e("TTTT", "E " + e.toString());
        }

    }



    @Override
    public void stop() {
        serialPortHelper.close();
    }


    public void roomState(int roomNum, byte state) {
//        iDoorState.doorState(roomNum, state);
    }

    public void weightState(int roomNum, long state) {

    }


    public static void sendtoPortBuffer(List<Byte> mBuffer) {
        byte[] bytes = new byte[mBuffer.size()];
        for (int i = 0; i < mBuffer.size(); i++) {
            bytes[i] = mBuffer.get(i);
        }
        String res = StringUtil.byte2HexStr(bytes);
        Log.e("TTT", "发送2 : " + res);

            serialPortHelper.send(bytes);


    }

    /**
     * 开门
     *
     * @param doornum
     */
    @Override
    public void openDoor(int doornum) {
        ArrayList<Byte> mbuffer = new ArrayList<>();
        mbuffer.add((byte) 0x00);
        mbuffer.add((byte) 0x07);
        mbuffer.add((byte) 0x11);
        mbuffer.add((byte) doornum);
        mbuffer.add((byte) 0x01);
        mbuffer.addAll(getCrc16(mbuffer));
        sendtoPortBuffer(mbuffer);
    }


    /**
     * 关门
     *
     * @param doornum
     */
    @Override
    public void closeDoor(int doornum) {
        ArrayList<Byte> mbuffer = new ArrayList<>();
        mbuffer.add((byte) 0x00);
        mbuffer.add((byte) 0x07);
        mbuffer.add((byte) 0x11);
        mbuffer.add((byte) doornum);
        mbuffer.add((byte) 0x00);
        mbuffer.addAll(getCrc16(mbuffer));
        sendtoPortBuffer(mbuffer);
    }


    /**
     * 查询重量
     *
     * @param doornum
     */
    @Override
    public void getWeight(int doornum) {

        ArrayList<Byte> mbuffer = new ArrayList<>();
        mbuffer.add((byte) 0x00);
        mbuffer.add((byte) 0x07);
        mbuffer.add((byte) 0x13);
        mbuffer.add((byte) doornum);
        mbuffer.add((byte) 0x01);
        mbuffer.addAll(getCrc16(mbuffer));
        sendtoPortBuffer(mbuffer);
    }

    /**
     * 重量清零
     *
     * @param doornum
     */
    @Override
    public void getWeightReset(int doornum) {
        ArrayList<Byte> mbuffer = new ArrayList<>();
        mbuffer.add((byte) 0x00);
        mbuffer.add((byte) 0x07);
        mbuffer.add((byte) 0x13);
        mbuffer.add((byte) doornum);
        mbuffer.add((byte) 0x02);
        mbuffer.addAll(getCrc16(mbuffer));
        sendtoPortBuffer(mbuffer);
    }

    /**
     * 重量校正1
     *
     * @param doornum
     */
    @Override
    public void getWeightCorrect1(int doornum) {
        ArrayList<Byte> mbuffer = new ArrayList<>();
        mbuffer.add((byte) 0x00);
        mbuffer.add((byte) 0x07);
        mbuffer.add((byte) 0x13);
        mbuffer.add((byte) doornum);
        mbuffer.add((byte) 0x03);
        mbuffer.addAll(getCrc16(mbuffer));
        sendtoPortBuffer(mbuffer);
    }

    /**
     * 重量校正2
     *
     * @param doornum
     */
    @Override
    public void getWeightCorrect2(int doornum) {
        ArrayList<Byte> mbuffer = new ArrayList<>();
        mbuffer.add((byte) 0x00);
        mbuffer.add((byte) 0x07);
        mbuffer.add((byte) 0x13);
        mbuffer.add((byte) doornum);
        mbuffer.add((byte) 0x04);
        mbuffer.addAll(getCrc16(mbuffer));
        sendtoPortBuffer(mbuffer);
    }

    /**
     * 开剪切
     *
     * @param doornum
     */
    @Override
    public void openCut(int doornum) {
//        appRuntime.setCut(true);
        ArrayList<Byte> mbuffer = new ArrayList<>();
        mbuffer.add((byte) 0x00);
        mbuffer.add((byte) 0x07);
        mbuffer.add((byte) 0x11);
        mbuffer.add((byte) doornum);
        mbuffer.add((byte) 0x11);
        mbuffer.addAll(getCrc16(mbuffer));
        sendtoPortBuffer(mbuffer);
    }

    /**
     * 关剪切
     *
     * @param doornum
     */
    @Override
    public void closeCut(int doornum) {
//        appRuntime.setCut(false);
        ArrayList<Byte> mbuffer = new ArrayList<>();
        mbuffer.add((byte) 0x00);
        mbuffer.add((byte) 0x07);
        mbuffer.add((byte) 0x11);
        mbuffer.add((byte) doornum);
        mbuffer.add((byte) 0x10);
        mbuffer.addAll(getCrc16(mbuffer));
        sendtoPortBuffer(mbuffer);
    }
    public void closeDoorState(int state) {
        ArrayList<Byte> mbuffer = new ArrayList<>();
        mbuffer.add((byte) 0x00);
        mbuffer.add((byte) 0x07);
        mbuffer.add((byte) 0x15);
        mbuffer.add((byte) state);
        mbuffer.add((byte) 0x01);
        mbuffer.addAll(getCrc16(mbuffer));
        sendtoPortBuffer(mbuffer);
    }
    /**
     * 开压缩
     *
     * @param doornum
     */
    @Override
    public void openZip(int doornum) {
//        ArrayList<Byte> mbuffer = new ArrayList<>();
//        mbuffer.add((byte) 0x00);
//        mbuffer.add((byte) 0x07);
//        mbuffer.add((byte) 0x11);
//        mbuffer.add((byte) doornum);
//        mbuffer.add((byte) 0x06);
//        mbuffer.addAll(getCrc16(mbuffer));
//        sendtoPortBuffer(mbuffer);
    }

    /**
     * 关压缩
     *
     * @param doornum
     */
    @Override
    public void closeZip(int doornum) {
//        ArrayList<Byte> mbuffer = new ArrayList<>();
//        mbuffer.add((byte) 0x00);
//        mbuffer.add((byte) 0x07);
//        mbuffer.add((byte) 0x11);
//        mbuffer.add((byte) doornum);
//        mbuffer.add((byte) 0x07);
//        mbuffer.addAll(getCrc16(mbuffer));
//        sendtoPortBuffer(mbuffer);

    }

    /**
     * 开门锁
     *
     * @param doornum
     */
    @Override
    public void openLock(int doornum) {

        ArrayList<Byte> mbuffer = new ArrayList<>();
        mbuffer.add((byte) 0x00);
        mbuffer.add((byte) 0x07);
        mbuffer.add((byte) 0x11);
        mbuffer.add((byte) doornum);
        mbuffer.add((byte) 0x02);
        mbuffer.addAll(getCrc16(mbuffer));
        sendtoPortBuffer(mbuffer);
    }

    @Override
    public void getState() {
        ArrayList<Byte> mbuffer = new ArrayList<>();
        mbuffer.add((byte) 0x00);
        mbuffer.add((byte) 0x07);
        mbuffer.add((byte) 0x14);
        mbuffer.add((byte) 0x73);
        mbuffer.add((byte) 0xFF);
        sendtoPortBuffer(mbuffer);
    }


    /**
     * rfid
     */
    @Override
    public void sendSingleRfid() {
        ArrayList<Byte> mbuffer = new ArrayList<>();
        mbuffer.add((byte) 0xBB);
        mbuffer.add((byte) 0x00);
        mbuffer.add((byte) 0x22);
        mbuffer.add((byte) 0x00);
        mbuffer.add((byte) 0x00);
        mbuffer.add((byte) 0x22);
        mbuffer.add((byte) 0x7E);
        sendtoPortBuffer(mbuffer);
    }

    @Override
    public void sendLoopRfid() {

    }

    /**
     * 故障上报
     */
    @Override
    public void fault() {
        ArrayList<Byte> mbuffer = new ArrayList<>();
        mbuffer.add((byte) 0x00);
        mbuffer.add((byte) 0x05);
        mbuffer.add((byte) 0x15);
        mbuffer.add((byte) 0xB3);
        mbuffer.add((byte) 0x5F);
        sendtoPortBuffer(mbuffer);
    }

    @Override
    public void deviceState() {

    }

    @Override
    public void reply07() {

    }

    @Override
    public void reply0d() {

    }

    @Override
    public boolean sendConfig(String str) {
        return false;
    }

//    @Override
//    public void getState() {
//        ArrayList<Byte> mbuffer = new ArrayList<>();
//        mbuffer.add((byte) 0x00);
//        mbuffer.add((byte) 0x05);
//        mbuffer.add((byte) 0x15);
//        mbuffer.add((byte) 0xB3);
//        mbuffer.add((byte) 0x5F);
//        sendtoPortBuffer(mbuffer);
//    }

    static ArrayList<Byte> getCrc16(ArrayList<Byte> arr_buff) {
        int len = arr_buff.size();

        // 预置 1 个 16 位的寄存器为十六进制FFFF, 称此寄存器为 CRC寄存器。
        int crc = 0xFFFF;
        int i, j;
        for (i = 0; i < len; i++) {
            // 把第一个 8 位二进制数据 与 16 位的 CRC寄存器的低 8 位相异或, 把结果放于 CRC寄存器
            crc = ((crc & 0xFF00) | (crc & 0x00FF) ^ (arr_buff.get(i) & 0xFF));
            for (j = 0; j < 8; j++) {
                // 把 CRC 寄存器的内容右移一位( 朝低位)用 0 填补最高位, 并检查右移后的移出位
                if ((crc & 0x0001) > 0) {
                    // 如果移出位为 1, CRC寄存器与多项式A001进行异或
                    crc = crc >> 1;
                    crc = crc ^ 0xA001;
                } else
                    // 如果移出位为 0,再次右移一位
                    crc = crc >> 1;
            }
        }
        return intToBytes2_fx(crc);
    }

    private static ArrayList<Byte> intToBytes2_fx(int value) {
        ArrayList<Byte> src = new ArrayList<Byte>();
        byte b1 = (byte) ((value >> 8) & 0xFF);
        byte b0 = (byte) (value & 0xFF);
        src.add(b0);
        src.add(b1);

        return src;
    }

    public static int bytesToInt2(byte[] bs) {

        int signedInt = ByteBuffer.wrap(bs).getInt();
        return signedInt;
    }

}
